package com.jlf.starter.advice;

import com.jlf.core.annotation.restful.RestfulToolkit;
import com.jlf.core.annotation.restful.controller.RestfulController;
import com.jlf.core.output.ResultWrapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.List;

/**
 * 输出的advice
 *
 * @author wujr
 * 2023/7/13
 * @version 1.0
 * 【变更历史】
 * [wujr 2023/7/13 1.0 新增]
 */
@ControllerAdvice
public class OutputAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, @NonNull Class<? extends HttpMessageConverter<?>> converterType) {
        Class<?> apiClass = returnType.getExecutable().getDeclaringClass();

        boolean apiPresent = apiClass.isAnnotationPresent(RestfulController.class);
        if (!apiPresent){
            Class<?> clz = returnType.getContainingClass();
            if (clz.isAnnotationPresent(RestfulController.class)){
                RestfulController apiController = clz.getAnnotation(RestfulController.class);
                if(!apiController.outputWrapper()){
                    // 该接口控制器都需要不需要定制包装输出，统一为json格式
                    return true;
                }
                return RestfulToolkit.isProduceJson(returnType);
            }
        } else {
            RestfulController apiController = apiClass.getAnnotation(RestfulController.class);
            if(!apiController.outputWrapper()){
                // 该接口控制器都需要不需要定制包装输出，统一为json格式
                return true;
            }
            return RestfulToolkit.isProduceJson(returnType);
        }

        return apiClass.isAssignableFrom(ExceptionAdvice.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, @NonNull MethodParameter returnType,
                                  @NonNull MediaType selectedContentType,
                                  @NonNull Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  @NonNull ServerHttpRequest request,
                                  @NonNull ServerHttpResponse response) {
        Object result = body;
        ResultWrapper<?> wrapper;
        if (!(body instanceof ResultWrapper)){
            // 注意：对于controller返回string类型的，需要在接口的注解中加入：
            // produces的注解：{"application/json;charset=utf-8"}
            if (body instanceof List){
                wrapper = ResultWrapper.ok((List<?>)body);
            }else{
                wrapper = ResultWrapper.ok(body);
            }
            result = wrapper;
        }else{
            wrapper = (ResultWrapper<?>)result;
        }
        return result;
    }
}
